--- sys/netinet/tcp_stacks/rack.c.orig
+++ sys/netinet/tcp_stacks/rack.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2016-2018
+ * Copyright (c) 2016-2019
  *	Netflix Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -203,6 +203,7 @@
 static int32_t rack_sack_block_limit = 128;
 static int32_t rack_use_sack_filter = 1;
 static int32_t rack_tlp_threshold_use = TLP_USE_TWO_ONE;
+static uint32_t rack_map_split_limit = 0;	/* unlimited by default */
 
 /* Rack specific counters */
 counter_u64_t rack_badfr;
@@ -228,6 +229,8 @@
 counter_u64_t rack_to_alloc;
 counter_u64_t rack_to_alloc_hard;
 counter_u64_t rack_to_alloc_emerg;
+counter_u64_t rack_alloc_limited_conns;
+counter_u64_t rack_split_limited;
 
 counter_u64_t rack_sack_proc_all;
 counter_u64_t rack_sack_proc_short;
@@ -261,6 +264,8 @@
 rack_ack_received(struct tcpcb *tp, struct tcp_rack *rack,
     struct tcphdr *th, uint16_t nsegs, uint16_t type, int32_t recovery);
 static struct rack_sendmap *rack_alloc(struct tcp_rack *rack);
+static struct rack_sendmap *rack_alloc_limit(struct tcp_rack *rack,
+    uint8_t limit_type);
 static struct rack_sendmap *
 rack_check_recovery_mode(struct tcpcb *tp,
     uint32_t tsused);
@@ -445,6 +450,8 @@
 		counter_u64_zero(rack_sack_proc_short);
 		counter_u64_zero(rack_sack_proc_restart);
 		counter_u64_zero(rack_to_alloc);
+		counter_u64_zero(rack_alloc_limited_conns);
+		counter_u64_zero(rack_split_limited);
 		counter_u64_zero(rack_find_high);
 		counter_u64_zero(rack_runt_sacks);
 		counter_u64_zero(rack_used_tlpmethod);
@@ -622,6 +629,11 @@
 	    OID_AUTO, "pktdelay", CTLFLAG_RW,
 	    &rack_pkt_delay, 1,
 	    "Extra RACK time (in ms) besides reordering thresh");
+	SYSCTL_ADD_U32(&rack_sysctl_ctx,
+	    SYSCTL_CHILDREN(rack_sysctl_root),
+	    OID_AUTO, "split_limit", CTLFLAG_RW,
+	    &rack_map_split_limit, 0,
+	    "Is there a limit on the number of map split entries (0=unlimited)");
 	SYSCTL_ADD_S32(&rack_sysctl_ctx,
 	    SYSCTL_CHILDREN(rack_sysctl_root),
 	    OID_AUTO, "inc_var", CTLFLAG_RW,
@@ -757,7 +769,19 @@
 	    SYSCTL_CHILDREN(rack_sysctl_root),
 	    OID_AUTO, "allocemerg", CTLFLAG_RD,
 	    &rack_to_alloc_emerg,
-	    "Total alocations done from emergency cache");
+	    "Total allocations done from emergency cache");
+	rack_alloc_limited_conns = counter_u64_alloc(M_WAITOK);
+	SYSCTL_ADD_COUNTER_U64(&rack_sysctl_ctx,
+	    SYSCTL_CHILDREN(rack_sysctl_root),
+	    OID_AUTO, "alloc_limited_conns", CTLFLAG_RD,
+	    &rack_alloc_limited_conns,
+	    "Connections with allocations dropped due to limit");
+	rack_split_limited = counter_u64_alloc(M_WAITOK);
+	SYSCTL_ADD_COUNTER_U64(&rack_sysctl_ctx,
+	    SYSCTL_CHILDREN(rack_sysctl_root),
+	    OID_AUTO, "split_limited", CTLFLAG_RD,
+	    &rack_split_limited,
+	    "Split allocations dropped due to limit");
 	rack_sack_proc_all = counter_u64_alloc(M_WAITOK);
 	SYSCTL_ADD_COUNTER_U64(&rack_sysctl_ctx,
 	    SYSCTL_CHILDREN(rack_sysctl_root),
@@ -1121,10 +1145,11 @@
 {
 	struct rack_sendmap *rsm;
 
-	counter_u64_add(rack_to_alloc, 1);
-	rack->r_ctl.rc_num_maps_alloced++;
 	rsm = uma_zalloc(rack_zone, M_NOWAIT);
 	if (rsm) {
+alloc_done:
+		counter_u64_add(rack_to_alloc, 1);
+		rack->r_ctl.rc_num_maps_alloced++;
 		return (rsm);
 	}
 	if (rack->rc_free_cnt) {
@@ -1132,14 +1157,46 @@
 		rsm = TAILQ_FIRST(&rack->r_ctl.rc_free);
 		TAILQ_REMOVE(&rack->r_ctl.rc_free, rsm, r_next);
 		rack->rc_free_cnt--;
-		return (rsm);
+		goto alloc_done;
 	}
 	return (NULL);
 }
 
+/* wrapper to allocate a sendmap entry, subject to a specific limit */
+static struct rack_sendmap *
+rack_alloc_limit(struct tcp_rack *rack, uint8_t limit_type)
+{
+	struct rack_sendmap *rsm;
+
+	if (limit_type) {
+		/* currently there is only one limit type */
+		if (rack_map_split_limit > 0 &&
+		    rack->r_ctl.rc_num_split_allocs >= rack_map_split_limit) {
+			counter_u64_add(rack_split_limited, 1);
+			if (!rack->alloc_limit_reported) {
+				rack->alloc_limit_reported = 1;
+				counter_u64_add(rack_alloc_limited_conns, 1);
+			}
+			return (NULL);
+		}
+	}
+
+	/* allocate and mark in the limit type, if set */
+	rsm = rack_alloc(rack);
+	if (rsm != NULL && limit_type) {
+		rsm->r_limit_type = limit_type;
+		rack->r_ctl.rc_num_split_allocs++;
+	}
+	return (rsm);
+}
+
 static void
 rack_free(struct tcp_rack *rack, struct rack_sendmap *rsm)
 {
+	if (rsm->r_limit_type) {
+		/* currently there is only one limit type */
+		rack->r_ctl.rc_num_split_allocs--;
+	}
 	rack->r_ctl.rc_num_maps_alloced--;
 	if (rack->r_ctl.rc_tlpsend == rsm)
 		rack->r_ctl.rc_tlpsend = NULL;
@@ -3955,7 +4012,7 @@
 		/*
 		 * Need to split this in two pieces the before and after.
 		 */
-		nrsm = rack_alloc(rack);
+		nrsm = rack_alloc_limit(rack, RACK_LIMIT_TYPE_SPLIT);
 		if (nrsm == NULL) {
 			/*
 			 * failed XXXrrs what can we do but loose the sack
@@ -4016,7 +4073,7 @@
 		goto do_rest_ofb;
 	}
 	/* Ok we need to split off this one at the tail */
-	nrsm = rack_alloc(rack);
+	nrsm = rack_alloc_limit(rack, RACK_LIMIT_TYPE_SPLIT);
 	if (nrsm == NULL) {
 		/* failed rrs what can we do but loose the sack info? */
 		goto out;
--- sys/netinet/tcp_stacks/tcp_rack.h.orig
+++ sys/netinet/tcp_stacks/tcp_rack.h
@@ -55,8 +55,10 @@
 	uint8_t r_sndcnt;	/* Retran count, not limited by
 				 * RACK_NUM_OF_RETRANS */
 	uint8_t r_in_tmap;	/* Flag to see if its in the r_tnext array */
-	uint8_t r_resv[3];
+	uint8_t r_limit_type;	/* is this entry counted against a limit? */
+	uint8_t r_resv[2];
 };
+#define RACK_LIMIT_TYPE_SPLIT	1
 
 TAILQ_HEAD(rack_head, rack_sendmap);
 
@@ -242,7 +244,7 @@
 	uint32_t rc_num_maps_alloced;	/* Number of map blocks (sacks) we
 					 * have allocated */
 	uint32_t rc_rcvtime;	/* When we last received data */
-	uint32_t rc_notused;
+	uint32_t rc_num_split_allocs;	/* num split map entries allocated */
 	uint32_t rc_last_output_to; 
 	uint32_t rc_went_idle_time;
 
@@ -311,7 +313,8 @@
 	uint8_t rack_tlp_threshold_use;
 	uint8_t rc_allow_data_af_clo: 1,
 		delayed_ack : 1,
-		rc_avail : 6;
+		alloc_limit_reported : 1,
+		rc_avail : 5;
 	uint8_t r_resv[2];	/* Fill to cache line boundary */
 	/* Cache line 2 0x40 */
 	struct rack_control r_ctl;
